#include "xdata/xdataformparserfactory.h"

namespace yoohoo_xdata {

const ProtocolKey XDataFormParserFactory::PROTOCOL_KEY = ProtocolKey("x", "jabber:x:data");

XDataFormParser::XDataFormParser() : _dataForm(0), _field(0), _item(0), _reported(0), _option(0) {
}

XDataFormParser::~XDataFormParser() {
	if (_dataForm) {
		delete _dataForm;
	}

	if (_field) {
		delete _field;
	}

	if (_item) {
		delete _item;
	}

	if (_reported) {
		delete _reported;
	}

	if (_option) {
		delete _option;
	}
}

XmppObject* XDataFormParser::obj() {
	return _dataForm;
}

bool XDataFormParser::processAttributes(QString path, QList<ParsingAttribute> attributes) {
	if ("x" == path) {
		if (_dataForm == 0) {
			_dataForm = new XDataForm;
		}
		
		foreach (ParsingAttribute attribute, attributes) {
			if ("type" == attribute.localName() && "" == attribute.prefix()) {
				if ("form" == attribute.value()) {
					_dataForm->setType(XDataForm::FORM);
				} else if ("result" == attribute.value()) {
					_dataForm->setType(XDataForm::RESULT);
				} else if ("submit" == attribute.value()) {
					_dataForm->setType(XDataForm::SUBMIT);
				} else if ("cancel" == attribute.value()) {
					_dataForm->setType(XDataForm::CANCEL);
				} else {
					return false;
				}
			} else {
				return false;
			}
		}
	} else if ("x/field" == path || "x/item/field" == path || "x/reported/field" == path) {
		_field = new XDataField;
		foreach (ParsingAttribute attribute, attributes) {
			if ("" == attribute.prefix() && "label" == attribute.localName()) {
				_field->setLabel(attribute.value());
			} else if ("" == attribute.prefix() && "type" == attribute.localName()) {
				QString type = attribute.value();
				if ("boolean" == type) {
					_field->setType(XDataField::BOOLEAN);
				} else if ("fixed" == type) {
					_field->setType(XDataField::FIXED);
				} else if ("hidden" == type) {
					_field->setType(XDataField::HIDDEN);
				} else if ("jid-multi" == type) {
					_field->setType(XDataField::JID_MULTI);
				} else if ("jid-single" == type) {
					_field->setType(XDataField::JID_SINGLE);
				} else if ("list-multi" == type) {
					_field->setType(XDataField::LIST_MULTI);
				} else if ("list-single" == type) {
					_field->setType(XDataField::LIST_SINGLE);
				} else if ("text-multi" == type) {
					_field->setType(XDataField::TEXT_MULTI);
				} else if ("text-private" == type) {
					_field->setType(XDataField::TEXT_PRIVATE);
				} else if ("text-single" == type) {
					_field->setType(XDataField::TEXT_SINGLE);
				} else {
					return false;
				}
			} else if ("" == attribute.prefix() && "var" == attribute.localName()) {
				_field->setVar(attribute.value());
			} else {
				return false;
			}
		}
	} else if ("x/field/option" == path || "x/reported/field/option" == path || "x/item/field/option" == path) {
		foreach (ParsingAttribute attribute, attributes) {
			if ("" == attribute.prefix() && "label" == attribute.localName()) {
				_option = new XDataOption;
				_option->setLabel(attribute.value());
			} else {
				return false;
			}
		}
	} else if ("x/reported" == path) {
		_reported = new XDataReported;
		if (attributes.size() != 0) {
			return false;
		}
	} else if ("x/item" == path) {
		_item = new XDataItem;
		if (attributes.size() != 0) {
			return false;
		}
	} else if ("x/title" == path || "x/instructions" == path || "x/field/desc" == path ||
			"x/field/required" == path || "x/reported/field/desc" == path || "x/item/field/desc" == path ||
				"x/field/required" == path || "x/reported/field/required" == path || "x/item/field/required" == path ||
					"x/field/value" == path || "x/reported/field/value" == path || "x/item/field/value" == path ||
						"x/field/option/value" == path || "x/item/field/option/value" == path ||
							"x/reported/field/option/value" == path) {
		if (attributes.size() != 0) {
			return false;
		}
	} else {
		return false;
	}

	return true;
}

bool XDataFormParser::processText(QString path, QString text) {
	if ("x" == path) {
		if (!text.isEmpty()) {
			return false;
		}
	} else if ("x/title" == path) {
		_dataForm->setTitle(text);
	} else if ("x/instructions" == path) {
		_dataForm->setInstructions(text);
	} else if ("x/field" == path) {
		if (!text.isEmpty()) {
			return false;
		}

		_dataForm->fields().append(*_field);
		delete _field;
		_field = 0;
	} else if ("x/item/field" == path) {
		if (!text.isEmpty()) {
			return false;
		}

		_item->fields().append(*_field);
		delete _field;
		_field = 0;
	} else if ("x/reported/field" == path) {
		if (!text.isEmpty()) {
			return false;
		}

		_reported->fields().append(*_field);
		delete _field;
		_field = 0;
	} else if ("x/item" == path) {
		if (!text.isEmpty()) {
			return false;
		}

		_dataForm->items().append(*_item);
		delete _item;
		_item = 0;
	} else if ("x/reported" == path) {
		if (!text.isEmpty()) {
			return false;
		}

		_dataForm->setReported(*_reported);
		delete _reported;
		_reported = 0;
	} else if ("x/field/desc" == path || "x/item/field/desc" == path ||
				"x/reported/field/desc" == path) {
		_field->setDesc(text);
	} else if ("x/field/required" == path || "x/item/field/required" == path ||
			"x/reported/field/required" == path) {
		if (!text.isEmpty()) {
			return false;
		}

		_field->setRequired(true);
	} else if ("x/field/value" == path || "x/item/field/value" == path ||
				"x/reported/field/value" == path) {
		_field->values().append(text);
	} else if ("x/field/option" == path || "x/item/field/option" == path ||
			"x/reported/field/option" == path) {
		_field->options().append(*_option);
		delete _option;
		_option = 0;
	} else if ("x/field/option/value" == path || "x/item/field/option/value" == path ||
			"x/reported/field/option/value" == path) {
		_option->setValue(text);
	} else {
		return false;
	}

	return true;
}

bool XDataFormParser::processEmbeddedObject(ProtocolKey protocolKey, XmppObject* object) {
	return false;
}

ProtocolKey XDataFormParserFactory::protocolKey() {
	return PROTOCOL_KEY;
}
	
XmppParser* XDataFormParserFactory::createParser() {
	return new XDataFormParser;
}

}
